* store QXmlStreamAttributes in xml_tag.
instead of arrays of char strings. This simplified xml_tag
handling.
Correct encoding issues with text and html formats.
Enhance test coverage of text and html formats.
* clean up xml attributes handling.
using fs_convert = void (*)(void*);
struct format_specific_data {
- long type;
- format_specific_data* next;
+ long type{0};
+ format_specific_data* next{nullptr};
- fs_destroy destroy;
- fs_copy copy;
- fs_convert convert;
+ fs_destroy destroy{nullptr};
+ fs_copy copy{nullptr};
+ fs_convert convert{nullptr};
};
class gb_color
auto* new_tag = new xml_tag;
new_tag->tagname = el;
- int attr_count = attr.size();
- const QXmlStreamNamespaceDeclarations nsdecl = reader->namespaceDeclarations();
- const int ns_count = nsdecl.size();
- new_tag->attributes = (char**)xcalloc(sizeof(char*),2*(attr_count+ns_count)+1);
- char** avcp = new_tag->attributes;
- for (int i = 0; i < attr_count; i++) {
- *avcp = xstrdup(attr[i].qualifiedName().toString());
- avcp++;
- *avcp = xstrdup(attr[i].value().toString());
- avcp++;
- }
- for (int i = 0; i < ns_count; i++) {
- *avcp = xstrdup(nsdecl[i].prefix().toString().prepend(nsdecl[i].prefix().isEmpty()? "xmlns" : "xmlns:"));
- avcp++;
- *avcp = xstrdup(nsdecl[i].namespaceUri().toString());
- avcp++;
- }
-
- *avcp = nullptr; // this indicates the end of the attribute name value pairs.
+ const QXmlStreamNamespaceDeclarations ns = reader->namespaceDeclarations();
+ new_tag->attributes.reserve(attr.size() + ns.size());
+ /*
+ * It was found to be faster to append one element at a time compared to
+ * a) assiging new_tag->attributes = attr, or
+ * b) appending in one step, new_tag.attributes.apppend(attr)
+ * Tested with on ubuntu bioinic with Qt 5.9.5 and a large Geocache file
+ * generated by Groundspeak.
+ */
+ for (const auto& a : attr) {
+ new_tag->attributes.append(a);
+ }
+ for (const auto& n : ns) {
+ QString prefix = n.prefix().toString().prepend(n.prefix().isEmpty()? "xmlns" : "xmlns:");
+ QString namespaceUri = n.namespaceUri().toString();
+ new_tag->attributes.append(prefix, namespaceUri);
+ }
if (cur_tag) {
if (cur_tag->child) {
}
static void
-write_tag_attributes(xml_tag* tag)
+write_attributes(const QXmlStreamAttributes& attributes)
{
- char** pa = tag->attributes;
- if (pa) {
- while (*pa) {
- writer->writeAttribute(pa[0], pa[1]);
- pa += 2;
- }
+ for (const auto& attribute : attributes) {
+ writer->writeAttribute(attribute.qualifiedName().toString(), attribute.value().toString());
}
}
{
while (tag) {
writer->writeStartElement(tag->tagname);
-
+ write_attributes(tag->attributes);
if (tag->cdata.isEmpty() && !tag->child) {
- write_tag_attributes(tag);
// No children? Self-closing tag.
writer->writeEndElement();
} else {
- write_tag_attributes(tag);
-
if (!tag->cdata.isEmpty()) {
writer->writeCharacters(tag->cdata);
}
}
}
-void free_gpx_extras(xml_tag* tag)
-{
- while (tag) {
- if (tag->child) {
- free_gpx_extras(tag->child);
- }
- if (tag->attributes) {
- char** ap = tag->attributes;
-
- while (*ap) {
- xfree(*ap++);
- }
-
- xfree(tag->attributes);
- }
-
- xml_tag* next = tag->sibling;
- delete tag;
- tag = next;
- }
-}
-
/*
* Handle the grossness of GPX 1.0 vs. 1.1 handling of linky links.
*/
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include <cstdint>
+#include <ctime> // for localtime
+
+#include <QtCore/QString> // for QString, operator!=
+#include <QtCore/QVector> // for QVector
+#include <QtCore/Qt> // for CaseInsensitive
#include "defs.h"
-#include "jeeps/gpsmath.h"
-#include "src/core/xmltag.h"
-#include <cstdio>
-#include <cstdlib>
+#include "gbfile.h" // for gbfprintf, gbfclose, gbfopen, gbfputs, gbfile
+#include "jeeps/gpsmath.h" // for GPS_Math_WGS84_To_UTM_EN
+#include "src/core/datetime.h" // for DateTime
+#include "src/core/xmltag.h" // for xml_findfirst, xml_attribute, xml_tag, fs_xml, xml_findnext
+
static gbfile* file_out;
static short_handle mkshort_handle;
GPS_Math_WGS84_To_UTM_EN(wpt->latitude, wpt->longitude,
&utme, &utmn, &utmz, &utmzc);
- gbfprintf(file_out, "\n<a name=\"%s\"><hr></a>\n", CSTRc(wpt->shortname));
+ gbfprintf(file_out, "\n<a name=\"%s\"><hr></a>\n", CSTR(wpt->shortname));
gbfprintf(file_out, "<table width=\"100%%\">\n");
- gbfprintf(file_out, "<tr><td><p class=\"gpsbabelwaypoint\">%s - ",(global_opts.synthesize_shortnames) ? CSTRc(mkshort_from_wpt(mkshort_handle, wpt)) : CSTRc(wpt->shortname));
+ gbfprintf(file_out, "<tr><td><p class=\"gpsbabelwaypoint\">%s - ",(global_opts.synthesize_shortnames) ? CSTR(mkshort_from_wpt(mkshort_handle, wpt)) : CSTR(wpt->shortname));
char* cout = pretty_deg_format(wpt->latitude, wpt->longitude, degformat[2], " ", 1);
gbfprintf(file_out, "%s (%d%c %6.0f %7.0f)", cout, utmz, utmzc, utme, utmn);
xfree(cout);
gbfprintf(file_out, "<br>\n");
if (wpt->description != wpt->shortname) {
if (wpt->HasUrlLink()) {
- char* d = html_entitize(CSTRc(wpt->description));
+ char* d = html_entitize(CSTR(wpt->description));
UrlLink link = wpt->GetUrlLink();
gbfprintf(file_out, "<a href=\"%s\">%s</a>", CSTR(link.url_), d);
xfree(d);
} else {
- gbfprintf(file_out, "%s", CSTRc(wpt->description));
+ gbfprintf(file_out, "%s", CSTR(wpt->description));
}
if (!wpt->gc_data->placer.isEmpty()) {
gbfprintf(file_out, " by %s", CSTR(wpt->gc_data->placer));
}
gbfprintf(file_out, "<p class=\"gpsbabelhint\"><strong>Hint:</strong> %s</p>\n", CSTR(hint));
} else if (!wpt->notes.isEmpty() && (wpt->description.isEmpty() || wpt->notes != wpt->description)) {
- gbfprintf(file_out, "<p class=\"gpsbabelnotes\">%s</p>\n", CSTRc(wpt->notes));
+ gbfprintf(file_out, "<p class=\"gpsbabelnotes\">%s</p>\n", CSTR(wpt->notes));
}
fs_xml* fs_gpx = nullptr;
logpart = xml_findfirst(curlog, "groundspeak:log_wpt");
if (logpart) {
- double lat = 0;
- double lon = 0;
- char* coordstr = xml_attribute(logpart, "lat");
- if (coordstr) {
- lat = atof(coordstr);
- }
- coordstr = xml_attribute(logpart, "lon");
- if (coordstr) {
- lon = atof(coordstr);
- }
- coordstr = pretty_deg_format(lat, lon, degformat[2], " ", 1);
+ double lat = xml_attribute(logpart->attributes, "lat").toDouble();
+ double lon = xml_attribute(logpart->attributes, "lon").toDouble();
+ char* coordstr = pretty_deg_format(lat, lon, degformat[2], " ", 1);
gbfprintf(file_out,
"<span class=\"gpsbabellogcoords\">%s</span><br>\n",
coordstr);
logpart = xml_findfirst(curlog, "groundspeak:text");
if (logpart) {
- char* encstr = xml_attribute(logpart, "encoded");
- int encoded = (toupper(encstr[0]) != 'F');
+ QString encstr = xml_attribute(logpart->attributes, "encoded");
+ bool encoded = !encstr.startsWith('F', Qt::CaseInsensitive);
QString s;
if (html_encrypt && encoded) {
# include <windows.h>
#endif
-#include <cctype> // for tolower, toupper
-#include <cmath> // for fabs
-#include <cstdio> // for sscanf, printf
-#include <cstdlib> // for atoi, atol, atof
-#include <cstring> // for strcmp
-#include <tuple> // for tuple, make_tuple, tie
-
-#include <QtCore/QByteArray> // for QByteArray
-#include <QtCore/QChar> // for QChar
-#include <QtCore/QDate> // for QDate
-#include <QtCore/QDateTime> // for QDateTime
-#include <QtCore/QFile> // for QFile
-#include <QtCore/QIODevice> // for operator|, QIODevice, QIODevice::Text, QIODevice::WriteOnly
-#include <QtCore/QList> // for QList
-#include <QtCore/QStaticStringData> // for QStaticStringData
-#include <QtCore/QString> // for QString, QStringLiteral, operator+, operator!=
-#include <QtCore/QXmlStreamAttributes> // for QXmlStreamAttributes
-#include <QtCore/Qt> // for ISODate
-#include <QtCore/QtGlobal> // for foreach, qint64, qPrintable
+#include <cctype> // for tolower, toupper
+#include <cmath> // for fabs
+#include <cstdio> // for sscanf, printf
+#include <cstdlib> // for atoi, atol, atof
+#include <cstring> // for strcmp
+#include <tuple> // for tuple, make_tuple, tie
+
+#include <QtCore/QByteArray> // for QByteArray
+#include <QtCore/QChar> // for QChar
+#include <QtCore/QDate> // for QDate
+#include <QtCore/QDateTime> // for QDateTime
+#include <QtCore/QFile> // for QFile
+#include <QtCore/QIODevice> // for operator|, QIODevice, QIODevice::Text, QIODevice::WriteOnly
+#include <QtCore/QList> // for QList
+#include <QtCore/QStaticStringData> // for QStaticStringData
+#include <QtCore/QString> // for QString, QStringLiteral, operator+, operator!=
+#include <QtCore/QStringList> // for QStringList
+#include <QtCore/QVector> // for QVector
+#include <QtCore/QXmlStreamAttributes> // for QXmlStreamAttributes
+#include <QtCore/Qt> // for ISODate
+#include <QtCore/QtGlobal> // for foreach, qint64, qPrintable
#include "defs.h"
#include "grtcirc.h" // for RAD, gcdist, radtometers
#include "src/core/datetime.h" // for DateTime
#include "src/core/file.h" // for File
+#include "src/core/logging.h" // for Warning, Fatal
#include "src/core/optional.h" // for optional
-#include <src/core/logging.h> // for Warning
#include "src/core/xmlstreamwriter.h" // for XmlStreamWriter
#include "src/core/xmltag.h" // for xml_findfirst, xml_tag, fs_xml, xml_attribute, xml_findnext
+#include "units.h" // for fmt_setunits, fmt_speed, fmt_altitude, fmt_distance, units_aviation, units_metric, units_nautical, units_statute
#include "xmlgeneric.h" // for cb_cdata, cb_end, cb_start, xg_callback, xg_string, xg_cb_type, xml_deinit, xml_ignore_tags, xml_init, xml_read, xg_tag_mapping
-#include "units.h"
+
// options
static char* opt_deficon = nullptr;
logpart = xml_findfirst(curlog, "groundspeak:text");
if (logpart) {
- char* encstr = xml_attribute(logpart, "encoded");
- int encoded = (toupper(encstr[0]) != 'F');
+ QString encstr = xml_attribute(logpart->attributes, "encoded");
+ bool encoded = !encstr.startsWith('F', Qt::CaseInsensitive);
QString s;
if (html_encrypt && encoded) {
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+ <title>GPSBabel HTML Output</title>
+ <style>
+ p.gpsbabelwaypoint { font-size: 120%; font-weight: bold }
+ </style>
+</head>
+<body>
+<p class="index">
+<a href="#GC7FA4">GC7FA4 - Points géodésiques du Québec</a><br>
+</p>
+
+<a name="GC7FA4"><hr></a>
+<table width="100%">
+<tr><td><p class="gpsbabelwaypoint">GC7FA4 - N46°08.000 W73°00.000 (18T 654491 5110806)<br>
+<a href="http://www.geocaching.com/seek/cache_details.aspx?guid=727f9d2c-f080-41f1-a2c9-a326ead462ed">Points géodésiques du Québec</a> by Sverdrup2</p></td>
+<td align="right"><p class="gpsbabelcacheinfo">1 / 1<br>
+Locationless (Reverse) Cache / Virtual</p></td></tr>
+<tr><td colspan="2"><p class="gpsbabeldescshort">LES COORDONÉES PUBLIÉES NE REPRÉSENTENT PAS LA LOCALISATION D'UNE CACHE
+PUBLISHED COORDINATES DO NOT REPRESENT THE LOCALIZATION OF A CACHE</p>
+<p class="gpsbabeldesclong">Le but de cette cache virtuelle est de trouver les points géodésiques du territoire québécois. Les points géodésiques sont faciles à identifier (capuchons de laiton au niveau du sol). Généralement, il y a un panneau de couleur orange sur un poteau à proximité du point. Sur ce panneau, le numéro du point est identifié. Aussi, la distance relative du panneau au point est indiquée.
+<P>
+Pour inscrire votre découverte, vous devez prendre en note le NUMÉRO DU POINT(inscrit sur le point même ou au centre du panneau)LA COORDONNÉE(en format HDDD MM.MM WGS84 datum ET UTM NAD83 indiquer la zone SVP)et L'ALTITUDE RELATIVE. Si le points n'est pas visible (il se peut qu'il soit sous quelques centimètres de terre) vous pouvez prendre la coordonnée à l'emplacement du panneau SI LA PRÉCISION DE VOTRE GPS EST SUPÉRIEUR À LA DISTANCE INSCRITE SUR LE PANNEAU (ex : Précison du GPS de 5m et distance au point inscrite sur le panneau de 3m).
+<P>
+Une photo du point ou du panneau et une description générale des lieux serait aussi des informations importantes.
+<P>
+Enfin, il faudrait aussi prendre en note l'organisme propriétaire du point géodésique. Au Québec il en existe plusieurs:
+<P>
+Le Service de la géodésie du Québec, Ministère des Ressources naturelles, Québec
+<P>
+La Division des levés géodésiques, Géomatique Canada, Secteur des sciences de la terre Ressources naturelles Canada
+<P>
+Le Service hydrographique du Canada, Direction des sciences, Pêches et Océans Canada et la Garde côtière canadienne, Pêches et Océans Canada
+<P>
+Et tout les anciens noms de ministères et/ou organisme
+<P>
+Des photos de points de même que des panneaux suivront bientôt.
+VOUS NE POUVEZ INSCRIRE QU'UN SEUL POINT GÉODÉSIQUE (UN POINT PAR GÉOCACHEUR)
+Bonne chance!
+
+<P>
+
+The goal of this virtual cache is to find the geodetic points of Québec’s territory. The geodetic points are easy to identify (Brass cap at ground level) Generally, there is an orange panel of on a post near the point. On this panel, the number of the point is identified. Also, the distance relating from the panel to the point is also indicated. In order to log your find, you must take in note THE NUMBER OF THE POINT(registered on the point or in the center of the panel) and THE COORDINATES(in format HDDD MM.MM WGS84 datum AND UTM NAD83 indicate the zone please)and THE ALTITUDE. If the point is not visible (it may be buried under few centimetres) you can take the coordinate at the panel IF THE ACCURACY OF YOUR GPS IS HIGHER Than the DISTANCE REGISTERED ON the PANEL. (Ex: accuracy of the GPS is 5m and the distance to the point registered on the panel is 3m).
+ <P>
+A picture of the point or panel and a general description of the places would be also significant information. Finally, it would also be important to take in note the organization owner of the geodetic point.
+In Quebec there are several:
+<P>
+The "Service de la géodésie du Québec, Ministère des Ressources naturelles Québec"
+The Geodetic Survey Division, Geomatics Canada, Earth Sciences Sector, Natural Resources Canada
+The Canadian Hydrographic Service, Sciences Directorate, Fisheries and Oceans Canada and the Canadian Coast Guard, Fisheries and Oceans Canada
+And all old names of ministries and/or organization
+<P>
+
+PICTURES of points and of the panels will follow soon. YOU CAN ONLY LOG ONE POINT (ONE POINT PER GEOCACHER)
+Good luck!</p>
+<p class="gpsbabellog">
+<span class="gpsbabellogtype">Found it</span> by <span class="gpsbabellogfinder">Christopher R & Pooh B</span> on <span class="gpsbabellogdate">2005-07-12</span><br>
+<span class="gpsbabellogcoords">N48°10.207 W53°58.097</span><br>
+This marker is not in Quebec but it is a Geodesic marker in Clarenville, Newfoundland, Canada!
+
+Found this one while hunting a traditional cache and thought of this cache right away!
+
+It is located on Bare Mountain in Clarenville - There are aactually two markers within 15 feet of one another on Bare Mountain...
+
+Smiles Pooh Bear
+
+Ce marqueur n'est pas au Québec mais c'est un marqueur géodésique dans Clarenville, Terre-Neuve, Canada!
+
+A trouvé celui-ci tandis que chasse une cachette traditionnelle et pensé à cette cachette tout de suite! Elle est située sur la montagne nue dans Clarenville - il y a aactually deux marqueurs à moins de 15 pieds d'un des autres sur la montagne nue... Ours De Pooh De Sourires</p>
+<p class="gpsbabellog">
+<span class="gpsbabellogtype">Found it</span> by <span class="gpsbabellogfinder">TravelBen</span> on <span class="gpsbabellogdate">2005-06-26</span><br>
+<span class="gpsbabellogcoords">N45°26.872 W73°56.410</span><br>
+[:D] 14h22
+
+Marqueur du Service de la Géodégie (c'est bien un "g" pas un "s") du Québec.
+
+Position Average (100 échantillons):
+N 45° 26.872 W 075° 56.410, 21 mètres d'altitude
+UTM: 18T E 582877 N 5033250
+
+Ce marqueur se trouve dans le ville de Senneville, sur un monument décrivant une page d'histoire du Québec, sur le bas côté avant droit.
+
+Près de la cache: Exo-07 La Jumelle de Loudiver (GCP3VE)</p>
+<p class="gpsbabellog">
+<span class="gpsbabellogtype">Found it</span> by <span class="gpsbabellogfinder">etasse</span> on <span class="gpsbabellogdate">2005-06-03</span><br>
+<span class="gpsbabellogcoords">N45°29.525 W75°43.005</span><br>
+MRN marker 94K4731 in Gatineau, QC. corner of Du Rhone and Gatineau Ave.
+
+Position Average
+N 45° 29.5247 W 075° 43.0049 59.49m
+UTM 18T 0443995 5037866
+
+Least Squares Average
+N 45° 29.5257 W 075° 43.0043 55.74m
+UTM 18T 0443996 5037868
+
+This pole has everything: An underground cable warning, a geodesic mark, a bus stop and a garage sale sign.
+
+Judging by the coordinates it looks like the coords should be 45°29'31.5" -75°43'0" I placed the GPS antenna right against the marker, to no avail.</p>
+<p class="gpsbabellog">
+<span class="gpsbabellogtype">Found it</span> by <span class="gpsbabellogfinder">Katou</span> on <span class="gpsbabellogdate">2005-06-03</span><br>
+<span class="gpsbabellogcoords">N46°37.091 W71°55.974</span><br>
+Un bo point géodésique a Lotbinière..en allant faire une nouvelle cache a l'île richelieu ;-)</p>
+<p class="gpsbabellog">
+<span class="gpsbabellogtype">Found it</span> by <span class="gpsbabellogfinder">Gps_Gulliver&DauphinBleu</span> on <span class="gpsbabellogdate">2005-05-29</span><br>
+<span class="gpsbabellogcoords">N45°32.449 W73°30.747</span><br>
+Point Geodesique situe near Port de Plaisance de Longueuil
+sur le bord du fleuve st-laurent.
+Il y a des sentiers et une grande piste cyclable
+Enjoy !</p>
+</td></tr></table>
+</body></html>
\ No newline at end of file
--- /dev/null
+-----------------------------------------------------------------------------
+GC7FA4 N46 08.000 W73 00.000 (18T 654491 5110806)
+Points géodésiques du Québec by Sverdrup2 - Locationless (Reverse) Cache / Virtual - (1 / 1)
+
+LES COORDONÉES PUBLIÉES NE REPRÉSENTENT PAS LA LOCALISATION D'UNE CACHE PUBLISHED COORDINATES DO NOT REPRESENT THE LOCALIZATION OF A CACHE
+
+Le but de cette cache virtuelle est de trouver les points géodésiques du territoire québécois. Les points géodésiques sont faciles à identifier (capuchons de laiton au niveau du sol). Généralement, il y a un panneau de couleur orange sur un poteau à proximité du point. Sur ce panneau, le numéro du point est identifié. Aussi, la distance relative du panneau au point est indiquée.
+ Pour inscrire votre découverte, vous devez prendre en note le NUMÉRO DU POINT(inscrit sur le point même ou au centre du panneau)LA COORDONNÉE(en format HDDD MM.MM WGS84 datum ET UTM NAD83 indiquer la zone SVP)et L'ALTITUDE RELATIVE. Si le points n'est pas visible (il se peut qu'il soit sous quelques centimètres de terre) vous pouvez prendre la coordonnée à l'emplacement du panneau SI LA PRÉCISION DE VOTRE GPS EST SUPÉRIEUR À LA DISTANCE INSCRITE SUR LE PANNEAU (ex : Précison du GPS de 5m et distance au point inscrite sur le panneau de 3m).
+ Une photo du point ou du panneau et une description générale des lieux serait aussi des informations importantes.
+ Enfin, il faudrait aussi prendre en note l'organisme propriétaire du point géodésique. Au Québec il en existe plusieurs:
+ Le Service de la géodésie du Québec, Ministère des Ressources naturelles, Québec
+ La Division des levés géodésiques, Géomatique Canada, Secteur des sciences de la terre Ressources naturelles Canada
+ Le Service hydrographique du Canada, Direction des sciences, Pêches et Océans Canada et la Garde côtière canadienne, Pêches et Océans Canada
+ Et tout les anciens noms de ministères et/ou organisme
+ Des photos de points de même que des panneaux suivront bientôt. VOUS NE POUVEZ INSCRIRE QU'UN SEUL POINT GÉODÉSIQUE (UN POINT PAR GÉOCACHEUR) Bonne chance!
+ The goal of this virtual cache is to find the geodetic points of Québec’s territory. The geodetic points are easy to identify (Brass cap at ground level) Generally, there is an orange panel of on a post near the point. On this panel, the number of the point is identified. Also, the distance relating from the panel to the point is also indicated. In order to log your find, you must take in note THE NUMBER OF THE POINT(registered on the point or in the center of the panel) and THE COORDINATES(in format HDDD MM.MM WGS84 datum AND UTM NAD83 indicate the zone please)and THE ALTITUDE. If the point is not visible (it may be buried under few centimetres) you can take the coordinate at the panel IF THE ACCURACY OF YOUR GPS IS HIGHER Than the DISTANCE REGISTERED ON the PANEL. (Ex: accuracy of the GPS is 5m and the distance to the point registered on the panel is 3m).
+ A picture of the point or panel and a general description of the places would be also significant information. Finally, it would also be important to take in note the organization owner of the geodetic point. In Quebec there are several:
+ The "Service de la géodésie du Québec, Ministère des Ressources naturelles Québec" The Geodetic Survey Division, Geomatics Canada, Earth Sciences Sector, Natural Resources Canada The Canadian Hydrographic Service, Sciences Directorate, Fisheries and Oceans Canada and the Canadian Coast Guard, Fisheries and Oceans Canada And all old names of ministries and/or organization
+ PICTURES of points and of the panels will follow soon. YOU CAN ONLY LOG ONE POINT (ONE POINT PER GEOCACHER) Good luck!
+
+Found it by Christopher R & Pooh B on 2005-07-12
+N48 10.207 W53 58.097
+This marker is not in Quebec but it is a Geodesic marker in Clarenville, Newfoundland, Canada!
+
+Found this one while hunting a traditional cache and thought of this cache right away!
+
+It is located on Bare Mountain in Clarenville - There are aactually two markers within 15 feet of one another on Bare Mountain...
+
+Smiles Pooh Bear
+
+Ce marqueur n'est pas au Québec mais c'est un marqueur géodésique dans Clarenville, Terre-Neuve, Canada!
+
+A trouvé celui-ci tandis que chasse une cachette traditionnelle et pensé à cette cachette tout de suite! Elle est située sur la montagne nue dans Clarenville - il y a aactually deux marqueurs à moins de 15 pieds d'un des autres sur la montagne nue... Ours De Pooh De Sourires
+
+Found it by TravelBen on 2005-06-26
+N45 26.872 W73 56.410
+[:D] 14h22
+
+Marqueur du Service de la Géodégie (c'est bien un "g" pas un "s") du Québec.
+
+Position Average (100 échantillons):
+N 45° 26.872 W 075° 56.410, 21 mètres d'altitude
+UTM: 18T E 582877 N 5033250
+
+Ce marqueur se trouve dans le ville de Senneville, sur un monument décrivant une page d'histoire du Québec, sur le bas côté avant droit.
+
+Près de la cache: Exo-07 La Jumelle de Loudiver (GCP3VE)
+
+Found it by etasse on 2005-06-03
+N45 29.525 W75 43.005
+MRN marker 94K4731 in Gatineau, QC. corner of Du Rhone and Gatineau Ave.
+
+Position Average
+N 45° 29.5247 W 075° 43.0049 59.49m
+UTM 18T 0443995 5037866
+
+Least Squares Average
+N 45° 29.5257 W 075° 43.0043 55.74m
+UTM 18T 0443996 5037868
+
+This pole has everything: An underground cable warning, a geodesic mark, a bus stop and a garage sale sign.
+
+Judging by the coordinates it looks like the coords should be 45°29'31.5" -75°43'0" I placed the GPS antenna right against the marker, to no avail.
+
+Found it by Katou on 2005-06-03
+N46 37.091 W71 55.974
+Un bo point géodésique a Lotbinière..en allant faire une nouvelle cache a l'île richelieu ;-)
+
+Found it by Gps_Gulliver&DauphinBleu on 2005-05-29
+N45 32.449 W73 30.747
+Point Geodesique situe near Port de Plaisance de Longueuil
+sur le bord du fleuve st-laurent.
+Il y a des sentiers et une grande piste cyclable
+Enjoy !
+
+-----------------------------------------------------------------------------
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class xml_tag {
- public:
- xml_tag() :
- attributes(nullptr),
- parent(nullptr),
- sibling(nullptr),
- child(nullptr) {}
+#ifndef SRC_CORE_XMLTAG_H
+#define SRC_CORE_XMLTAG_H
+#include <QtCore/QString> // for QString
+#include <QtCore/QXmlStreamAttributes> // for QXmlStreamAttributes
+
+#include "defs.h"
+
+class xml_tag
+{
+public:
QString tagname;
QString cdata;
QString parentcdata;
- char** attributes;
- xml_tag* parent;
- xml_tag* sibling;
- xml_tag* child;
+ QXmlStreamAttributes attributes;
+ xml_tag* parent{nullptr};
+ xml_tag* sibling{nullptr};
+ xml_tag* child{nullptr};
};
-xml_tag* xml_findfirst(xml_tag* root, const char* tagname);
-xml_tag* xml_findnext(xml_tag* root, xml_tag* cur, const char* tagname);
-char* xml_attribute(xml_tag* tag, const char* attrname);
-void free_gpx_extras(xml_tag* tag);
+xml_tag* xml_findfirst(xml_tag* root, const QString& tagname);
+xml_tag* xml_findnext(xml_tag* root, xml_tag* cur, const QString& tagname);
+QString xml_attribute(const QXmlStreamAttributes& attributes, const QString& attrname);
struct fs_xml {
format_specific_data fs;
- xml_tag* tag;
+ xml_tag* tag{nullptr};
};
fs_xml* fs_xml_alloc(long type);
+
+#endif // SRC_CORE_XMLTAG_H
gpsbabel -i gpx -f ${REFERENCE}/gc/GCGCA8.gpx -o html,logs -F ${TMPDIR}/gc_logs.html
compare ${REFERENCE}/gc/GCGCA8_logs~html.txt ${TMPDIR}/gc_logs.html
+
+gpsbabel -i gpx -f ${REFERENCE}/gc/GC7FA4.gpx \
+ -o html,logs -F ${TMPDIR}/GC7FA4.html \
+ -o text,logs -F ${TMPDIR}/GC7FA4.text
+compare ${REFERENCE}/gc/GC7FA4.html ${TMPDIR}/GC7FA4.html
+compare ${REFERENCE}/gc/GC7FA4.text ${TMPDIR}/GC7FA4.text
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include <cstdint>
+#include <ctime> // for localtime
+
+#include <QtCore/QString> // for QString, operator!=
+#include <QtCore/QVector> // for QVector
+#include <QtCore/Qt> // for CaseInsensitive
#include "defs.h"
-#include "jeeps/gpsmath.h"
-#include "src/core/xmltag.h"
-#include <cctype>
-#include <cstdlib>
+#include "gbfile.h" // for gbfprintf, gbfputs, gbfclose, gbfopen, gbfile
+#include "jeeps/gpsmath.h" // for GPS_Math_WGS84_To_UTM_EN
+#include "src/core/datetime.h" // for DateTime
+#include "src/core/xmltag.h" // for xml_findfirst, xml_attribute, xml_tag, fs_xml, xml_findnext
+
static gbfile* file_out;
static short_handle mkshort_handle;
}
xasprintf(&tmpout2, "%s (%d%c %6.0f %7.0f)%s", tmpout1, utmz, utmzc, utme, utmn, altout);
gbfprintf(file_out, "%-16s %59s\n",
- (global_opts.synthesize_shortnames) ? CSTRc(mkshort_from_wpt(mkshort_handle, wpt)) : CSTRc(wpt->shortname),
+ (global_opts.synthesize_shortnames) ? CSTR(mkshort_from_wpt(mkshort_handle, wpt)) : CSTR(wpt->shortname),
tmpout2);
xfree(tmpout2);
xfree(tmpout1);
logpart = xml_findfirst(curlog, "groundspeak:log_wpt");
if (logpart) {
- double lat = 0;
- double lon = 0;
- char* coordstr = xml_attribute(logpart, "lat");
- if (coordstr) {
- lat = atof(coordstr);
- }
- coordstr = xml_attribute(logpart, "lon");
- if (coordstr) {
- lon = atof(coordstr);
- }
- coordstr = pretty_deg_format(lat, lon, degformat[2], " ", 0);
+ double lat = xml_attribute(logpart->attributes, "lat").toDouble();
+ double lon = xml_attribute(logpart->attributes, "lon").toDouble();
+ char* coordstr = pretty_deg_format(lat, lon, degformat[2], " ", 0);
gbfprintf(file_out, "%s\n", coordstr);
xfree(coordstr);
}
logpart = xml_findfirst(curlog, "groundspeak:text");
if (logpart) {
- char* encstr = xml_attribute(logpart, "encoded");
- int encoded = (toupper(encstr[0]) != 'F');
+ QString encstr = xml_attribute(logpart->attributes, "encoded");
+ bool encoded = !encstr.startsWith('F', Qt::CaseInsensitive);
QString s;
if (txt_encrypt && encoded) {
*/
-#include <cctype> // for isspace, isalpha, ispunct, tolower, toupper
-#include <cerrno> // for errno
-#include <cmath> // for fabs, floor
-#include <cstdarg> // for va_list, va_end, va_start, va_copy
-#include <cstdint> // for uint32_t
-#include <cstdio> // for size_t, vsnprintf, FILE, fopen, printf, sprintf, stderr, stdin, stdout
-#include <cstdlib> // for abs, getenv, calloc, free, malloc, realloc
-#include <cstring> // for strlen, strcat, strstr, memcpy, strcmp, strcpy, strdup, strchr, strerror
-#include <ctime> // for mktime, localtime
-
-#include <QtCore/QByteArray> // for QByteArray
-#include <QtCore/QChar> // for QChar, operator<=, operator>=
-#include <QtCore/QCharRef> // for QCharRef
-#include <QtCore/QDateTime> // for QDateTime
-#include <QtCore/QFileInfo> // for QFileInfo
-#include <QtCore/QList> // for QList
-#include <QtCore/QString> // for QString, operator+
-#include <QtCore/QTextCodec> // for QTextCodec
-#include <QtCore/QTextStream> // for operator<<, QTextStream, qSetFieldWidth, endl, QTextStream::AlignLeft
-#include <QtCore/Qt> // for CaseInsensitive
-#include <QtCore/QtGlobal> // for qPrintable
+#include <cctype> // for isspace, isalpha, ispunct, tolower, toupper
+#include <cerrno> // for errno
+#include <cmath> // for fabs, floor
+#include <cstdarg> // for va_list, va_end, va_start, va_copy
+#include <cstdio> // for size_t, vsnprintf, FILE, fopen, printf, sprintf, stderr, stdin, stdout
+#include <cstdint> // for uint32_t
+#include <cstdlib> // for abs, getenv, calloc, free, malloc, realloc
+#include <cstring> // for strlen, strcat, strstr, memcpy, strcmp, strcpy, strdup, strchr, strerror
+#include <ctime> // for mktime, localtime
+
+#include <QtCore/QByteArray> // for QByteArray
+#include <QtCore/QChar> // for QChar, operator<=, operator>=
+#include <QtCore/QCharRef> // for QCharRef
+#include <QtCore/QDateTime> // for QDateTime
+#include <QtCore/QFileInfo> // for QFileInfo
+#include <QtCore/QList> // for QList
+#include <QtCore/QString> // for QString
+#include <QtCore/QStringRef> // for QStringRef
+#include <QtCore/QTextCodec> // for QTextCodec
+#include <QtCore/QTextStream> // for operator<<, QTextStream, qSetFieldWidth, endl, QTextStream::AlignLeft
+#include <QtCore/QXmlStreamAttribute> // for QXmlStreamAttribute
+#include <QtCore/Qt> // for CaseInsensitive
+#include <QtCore/QtGlobal> // for qAsConst, QAddConst<>::Type, qPrintable
#include "defs.h"
-#include "cet.h" // for cet_utf8_to_ucs4
-#include "src/core/datetime.h" // for DateTime
-#include "src/core/xmltag.h"
+#include "cet.h" // for cet_utf8_to_ucs4
+#include "src/core/datetime.h" // for DateTime
+#include "src/core/xmltag.h" // for xml_tag, xml_attribute, xml_findfirst, xml_findnext
// First test Apple's clever macro that's really a runtime test so
return cur;
}
-xml_tag* xml_findnext(xml_tag* root, xml_tag* cur, const char* tagname)
+xml_tag* xml_findnext(xml_tag* root, xml_tag* cur, const QString& tagname)
{
xml_tag* result = cur;
do {
return result;
}
-xml_tag* xml_findfirst(xml_tag* root, const char* tagname)
+xml_tag* xml_findfirst(xml_tag* root, const QString& tagname)
{
return xml_findnext(root, root, tagname);
}
-char* xml_attribute(xml_tag* tag, const char* attrname)
+QString xml_attribute(const QXmlStreamAttributes& attributes, const QString& attrname)
{
- char* result = nullptr;
- if (tag->attributes) {
- char** attr = tag->attributes;
- while (attr && *attr) {
- if (0 == case_ignore_strcmp(*attr, attrname)) {
- result = attr[1];
- break;
- }
- attr+=2;
+ for (const auto& attribute : attributes) {
+ if (attribute.qualifiedName().compare(attrname, Qt::CaseInsensitive) == 0) {
+ return attribute.value().toString();
}
}
- return result;
+ return QString();
}
const QString get_filename(const QString& fname)
*/
+#include <QtCore/QString> // for QString
+#include <QtCore/QXmlStreamAttributes> // for QXmlStreamAttributes
+
#include "defs.h"
-#include "cet_util.h"
#include "src/core/xmltag.h"
-#include <cstddef>
-#include <cstdio>
-#include <cstring>
static void
free_xml_tag(xml_tag* tag)
{
while (tag) {
if (tag->child) {
- free_gpx_extras(tag->child);
- }
- if (tag->attributes) {
- char** ap = tag->attributes;
-
- while (*ap) {
- xfree(*ap++);
- }
-
- xfree(tag->attributes);
+ free_xml_tag(tag->child);
}
xml_tag* next = tag->sibling;
xml_tag* res = new xml_tag;
*copy = res;
-// memcpy(res, src, sizeof(xml_tag));
res->tagname = (src->tagname);
res->cdata = (src->cdata);
res->parentcdata = (src->parentcdata);
- if (src->attributes) {
- char** ap = src->attributes;
- int count = 0;
- while (*ap) {
- count++;
- ap++;
- }
- res->attributes = (char**)xcalloc(count+1, sizeof(char*));
- ap = src->attributes;
- auto ap2 = res->attributes;
- while (*ap) {
- *ap2 = xstrdup(*ap);
- ap++;
- ap2++;
- }
- }
+ res->attributes = src->attributes;
res->parent = parent;
copy_xml_tag(&(res->sibling), src->sibling, parent);
copy_xml_tag(&(res->child), src->child, res);
}
-static void
-convert_xml_tag(xml_tag* tag)
-{
- if (tag == nullptr) {
- return;
- }
-
-// tag->cdata = cet_convert_string(tag->cdata);
-// tag->parentcdata = cet_convert_string(tag->parentcdata);
- tag->cdata = tag->cdata;
- tag->parentcdata = tag->parentcdata;
-
- char** ap = tag->attributes;
- while (*ap) {
- *ap = cet_convert_string(*ap);
- ap++;
- }
- convert_xml_tag(tag->sibling);
- convert_xml_tag(tag->child);
-}
-
static void
fs_xml_destroy(void* fs)
{
*copy = nullptr;
return;
}
- *copy = (void*)fs_xml_alloc(src->fs.type);
- memcpy(*copy, source, sizeof(fs_xml));
- copy_xml_tag(&(((fs_xml*)(*copy))->tag), src->tag, nullptr);
-}
+ fs_xml* res = new fs_xml;
+ *copy = res;
-static void
-fs_xml_convert(void* fs)
-{
- fs_xml* xml = (fs_xml*)fs;
- if (xml) {
- convert_xml_tag(xml->tag);
- }
+ res->fs = src->fs;
+ copy_xml_tag(&(res->tag), src->tag, nullptr);
}
fs_xml* fs_xml_alloc(long type)
result->fs.type = type;
result->fs.copy = fs_xml_copy;
result->fs.destroy = fs_xml_destroy;
- result->fs.convert = fs_xml_convert;
+ result->fs.convert = nullptr;
return result;
}